package org.benjamin.lending.service.impl;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.management.Query;

import org.apache.commons.codec.digest.HmacUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.benjamin.lending.domain.entity.Queue;
import org.benjamin.lending.domain.entity.TransactRequest;
import org.benjamin.lending.domain.entity.TransactRequest.Status;
import org.benjamin.lending.domain.form.Subledger;
import org.benjamin.lending.domain.transact.BasicOutBean;
import org.benjamin.lending.repository.QueueRepository;
import org.benjamin.lending.repository.TransactRequestRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;


/**
 * 以后要改名，该类是对SumapayTransactServiceImpl类的补充
 * @author 黄文杰
 *
 */
@Aspect
public class TransactAfterReturn{
	
	@Value("${sumapay.merchantCode}")
	private String merchantCode;
	
	@Value("${sumapay.secretKey}")
	private String securityKey;
	
	@Autowired
	private TransactRequestRepository transactRequestRepository;
	
	@Autowired
	private QueueRepository queueRepository;
	
	private Logger logger = LogManager.getLogger();

	@Pointcut("execution(* org.benjamin.lending.service.impl.SumapayTransactServiceImpl.*(..))")
	private void anyMethod() {};
	
	@Pointcut("execution(* org.benjamin.lending.service.impl.SumapayTransactServiceImpl.*Request(..))")
	private void requestMethod() {};

	@Pointcut("execution(* org.benjamin.lending.service.impl.SumapayTransactServiceImpl.*Response(..))")
	private void responseMethod(){};
	
	@Before("anyMethod()")
	public void doBefore() {
		logger.info("dsadsa");
	}

	@AfterReturning(pointcut = "requestMethod()",returning = "basicOutBean")
	public void doAfter(BasicOutBean basicOutBean) throws RuntimeException {
		logger.info("返回执行参数");
		String requestId = this.createRequestId();
		Assert.hasText(basicOutBean.getTransactBean().getTargetUrl(),"Url参数不能为Null");
		basicOutBean.getTransactBean().getParamterMap().put("merchantCode", this.merchantCode);
		basicOutBean.getTransactBean().getParamterMap().put("successReturnUrl", "http://localhost:8080/lending-web/successPage");
		basicOutBean.getTransactBean().getParamterMap().put("failReturnUrl", "http://localhost:8080/lending-web/failPage");
		basicOutBean.getTransactBean().getParamterMap().put("noticeUrl", "http://localhost:8080/lending-web/transact/response/"+requestId);

		basicOutBean.getTransactBean().getParamterMap().put("requestId",requestId);
		Object temp = basicOutBean.getTransactBean().getSubledger();
		if(temp != null) {
			List<Subledger> subledgers = (ArrayList<Subledger>)temp;
			try {
				ObjectMapper objectMapper = new ObjectMapper();
				String result = objectMapper.writeValueAsString(subledgers);
				logger.debug("成功将分账列表转换成JSON格式:{}",result);
				basicOutBean.getTransactBean().getParamterMap().put("subledgerList", result);
			} catch (JsonProcessingException e) {
				logger.error(e.getMessage(),e);
				throw new IllegalArgumentException("分账列表转换JSON格式出错:"+e.getMessage());
			}
		}
		basicOutBean.getTransactBean().setId(requestId);
		String[] sigNames = basicOutBean.getSignatureNames();
		StringBuffer stringBuffer = new StringBuffer();
		logger.info("加密操作");
		for(String sigName : sigNames) {
			temp = basicOutBean.getTransactBean().getParamterMap().get(sigName);
			if(temp != null) {
				String sigValue = temp.toString();
				stringBuffer.append(sigValue);
			}else {
				logger.warn("当前加密参数【{}】未能在封装参数组获取到",sigName);
			}
		}
		String signature = stringBuffer.toString();
		logger.info("加密明文:{}",signature);
		signature = HmacUtils.hmacMd5Hex(this.securityKey,signature);
		logger.info("加密成功，加密密文：{}",signature);
		basicOutBean.getTransactBean().getParamterMap().put("signature", signature);
		
		
		try {
			Map<String,Object> paramterMap = basicOutBean.getTransactBean().getParamterMap();
			logger.info("准备保存交易记录");
			TransactRequest transactRequest = basicOutBean.getTransactRequest();
			transactRequest.setId(paramterMap.get("requestId").toString());
			transactRequest.setBorrowInfo(basicOutBean.getBorrowInfo());
			if(transactRequest.getMemberInfo() == null) {
				transactRequest.setMemberInfo(basicOutBean.getMemberInfo());	
			}
			if(basicOutBean.getOrigParam() != null) {
				String origParam = new ObjectMapper().writeValueAsString(basicOutBean.getOrigParam());
				transactRequest.setOrigParam(origParam);
			}
			transactRequest.setPackData(new ObjectMapper().writeValueAsString(paramterMap));
			if(basicOutBean.isMq()) {
				transactRequest.setStatus(Status.READY);
			}else {
				transactRequest.setStatus(Status.SEND);
			}
			transactRequest.setTargetUrl(basicOutBean.getTransactBean().getTargetUrl());
			logger.info("开始保存交易信息");
			this.transactRequestRepository.save(transactRequest);
			logger.info("保存交易信息成功");
			if(basicOutBean.isMq()) {
				logger.info("当前操作是MQ处理，封装参数保存到Queue表中");
				
				String origMessage = new ObjectMapper().writeValueAsString(basicOutBean.getTransactBean());
				Queue queue = new Queue();
				Assert.hasText(basicOutBean.getQueueName(), "当前Queue任务QueueName必须存在");
				queue.setQueueName(basicOutBean.getQueueName());
				queue.setOrigMessage(origMessage);
				queue.setCreateTime(new Timestamp(System.currentTimeMillis()));
				this.queueRepository.save(queue);
				logger.info("完成保存Queue任务");
			}
			
		}catch(NullPointerException e) {
			logger.error(e.getMessage(),e);
		}catch(Exception e) {
			logger.error(e.getMessage(),e);
			throw new IllegalArgumentException(e.getMessage());
		}
	}
	
	@AfterReturning(pointcut = "responseMethod()",returning = "transactRequest")
	public void afterResponse(TransactRequest transactRequest) {
		logger.debug("AOP响应反馈操作");
		transactRequest.setProcessingTime(new Timestamp(System.currentTimeMillis()));
		this.transactRequestRepository.save(transactRequest);
	}
	
	private String createRequestId() {
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMdd");
		String requestId = dateFormat.format(new Date());
		requestId = requestId + RandomStringUtils.randomNumeric(12);
		return requestId;
	}
}
